﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Snowdreamist.ComponentModel.Plugin;

namespace Snowdreamist.Windows.Navigation.Primitives
{
    public class UriPrefixSelector
    {
        private static readonly ImportedPluginProperty<UriPrefixRegistry> RegistriesProperty
            = ImportedPluginProperty.Create<UriPrefixRegistry>(
                new ContractMetadata(new Guid("FFB2DC8B-D8DA-4304-A835-F7BEA18CBC35"), null, typeof(INavigationHandler), CandidateMode.ZeroOrMore, typeof(NavigationHandlerRepository)
                ));

        public UriPrefixSelector()
        {
            // register composed registries
            if (this.Registries != null)
                foreach (var registry in this.Registries)
                    try
                    {
                        this.Register(registry);
                    }
                    catch (Exception error)
                    {
                        // log
                    }
        }

        public void Register(UriPrefixRegistry registry)
        {
            if (registry == null)
                throw new ArgumentNullException("registry");
            if (registry.Prefix == null)
                throw new ArgumentException("Invalid prefix");

            lock (this)
            {
                if (this._prefixDict.ContainsKey(registry.Prefix))
                    throw new ValueExistsException("Prefix " + registry.Prefix + " has already registered");
                this._prefixDict.Add(registry.Prefix, registry);
            }
        }

        public void UnRegister(string prefix)
        {
            if (prefix == null)
                throw new ArgumentNullException("prefix");
            lock (this)
            {
                this._prefixDict.Remove(prefix);
            }
        }

        public string Select(string uri)
        {
            if (uri == null)
                throw new ArgumentNullException("uri");

            lock (this)
            {
                foreach (var registry in this._prefixDict.OrderByDescending(p => p.Key.Length).Select(p => p.Value))
                {
                    if (uri.StartsWith(registry.Prefix))
                        return registry.HandlerName;
                }
            }

            return null;
        }

        #region private

        private readonly Dictionary<string, UriPrefixRegistry> _prefixDict = new Dictionary<string, UriPrefixRegistry>();

        private IEnumerable<UriPrefixRegistry> Registries
        {
            get
            {
                return RegistriesProperty.GetValues(this);
            }
        }

        #endregion private
    }
}